<?php
	/**
	 * 
	 * Redistribution and use in source and binary forms, with or without
	 * modification, are permitted provided that the following conditions are met:
	 *
	 *     * Redistributions of source code must retain the above copyright
	 *       notice, this list of conditions and the following disclaimer.
	 *     * Redistributions in binary form must reproduce the above copyright
	 *       notice, this list of conditions and the following disclaimer in the
	 *       documentation and/or other materials provided with the distribution.
	 *     * Neither the name of the University of California, Berkeley nor the
	 *       names of its contributors may be used to endorse or promote products
	 *       derived from this software without specific prior written permission.
	 *
	 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY
	 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
	 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
	 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
	 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
	 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
	 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
	 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
	 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	 * 
	 * 
	 * Arquivo de inicialização do gSQLite
	 * @author Bruno Pitteli Gonçalves <scorninpc<at>gmail<dot>com>
	 * @version 0.1
	 * @license BSD license
	 *
	 *	Change log
	 *	0.1:
	 *		Class initialize methods
	 */
	 
	/**
	 * SQLITEresultSet
	 * Escrito por Bruno Pitteli Gonçalves <scorninpc()gmail*com>
	 * Classe que trata o resultado de uma query
	 */
	class SQLITEresultSet
	{
		/*
		 *	Variavel que armazena o resultado da query
		 *	@name $__resultSet
		 *	@access private
		 */
		private $__resultSet = null;
		
		/*
		 *	Variavel que armazena o resultado da query
		 *	@name $__results
		 *	@access private
		 */
		private $__results = null;

		/*
		 *	Variavel incando o total de linhas
		 *	@name $__RecordCount
		 *	@access private
		 */
		private $__RecordCount;
		
		/*
		 *	Variavel incando o final dos resultados
		 *	@name $EOF
		 *	@access public
		 */
		public $EOF = false;
		
		/*
		 *	Vetor que armazena os campos da linha
		 *	@name $Fields
		 *	@access public
		 */

		/*
		 *	Construtor da classe
		 *	@name __construct
		 *	@access public
		 *	@param $res - resultset retornado na execução de uma query
		 */
		public function __construct($res)
		{
			$this->__resultSet = $res;
			
			// Get rows count
		 	$this->__RecordCount = count($this->__resultSet->fetchAll());

			// Close execute again
			$this->__resultSet->closeCursor();
			$this->__resultSet->execute();

			// Move to first
			$this->MoveNext();
		} // __construct
		
		/*
		 *	Método que move o cursor do resultset
		 *	@name MoveNext
		 *	@access public
		 */
		public function MoveNext()
		{
			if(!$this->Fields = $this->__resultSet->fetch(PDO::FETCH_BOTH))
			{
				$this->EOF = FALSE;
			}
			else
			{
				$this->EOF = TRUE;
			}
		} // MoveNext

		/*
		 *	Método que retorna um só valor do resultset
		 *	@access public
		 *	@name FetchOne
		 *	@param	$col - Coluna a retornar
		 */
		public function FetchOne($col)
		{
			return $this->__resultSet->fetchColumn($col);
		}
		
		/*
		 *	Método que retorna a quantidade de linhas selecionadas
		 *	@name RecordCount
		 *	@access Public
		 *	@return	integer
		 */
		 public function RecordCount()
		 {
		 	return $this->__RecordCount;
		 } // RecordCount

		/*
		 *	Método que retorna a quantidade de colunas selecionadas
		 *	@name FieldsCount
		 *	@access Public
		 *	@return	integer
		 */
		 public function FieldsCount()
		 {
		 	return $this->__resultSet->columnCount();
		 } // RecordCount
		 
		 /*
		 *	Método que retorna a nome dos campos
		 *	@name FieldsName
		 *	@access Public
		 *	@return	array
		 */
		 public function FieldsName()
		 {
			$names = array();
			foreach($this->Fields as $field => $value)
			{
				if(!is_numeric($field))
				{
					$names[] = $field;
				}
			}
			return $names;
		 } // RecordCount
	}
	
	/*******
	 * SQLITE
	 * Escrito por Bruno Pitteli Gonçalves <scorninpc()gmail*com>
	 * Classe que trata o banco de dados
	 */
	class SQLITE {
	
		/*
		 *	Variavel que armazena a conexao com o banco de dados
		 *	@name $ConnectionLink
		 *	@access private
		 */
		private $ConnectionLink;
		
		/*
		 *	Variavel que armazena o nome do banco de dados
		 *	@name $DBname
		 *	@access private
		 */
		private $DBname;
		
		/*
		 *	Variavel que armazena o nome do arquivo de log
		 *	@name $LOGFile
		 *	@access private
		 */
		private $LOGFile = 'log-sqlite-bad_query.log';
		
		/*
		 *	Variavel que armazena o ultimo erro ocorrido
		 *	@name $LastError
		 *	@access public
		 */
		public $LastError = '';
		
		/*
		 *	Variavel que armazena o ultimo sql executado
		 *	@name $SQL
		 *	@access public
		 */
		public $SQL = '';
		
		/*
		 *	Variavel que armazena o nome do script que está executando a classe
		 *	@name $scriptName
		 *	@access public
		 */
		public $scriptName = '';
		
		/*
		 *	Construtor da classe
		 *	@name __construct
		 *	@access public
		 *	@param	$file - Endereço do arquivo do banco de dads
		 */
		public function __construct($file)
		{
			$this->DBname = utf8_encode($file);
			$this->connect();
		} // __construct

		/*
		 *	Fecha o arquivo de dados
		 *	@name disconnect
		 *	@access public
		 *	@return NULL
		 */
		public function disconnect()
		{
			unset($this->ConnectionLink);
		}

		/*
		 *	Fecha e abre o arquivo novamente
		 *	@name reconnect
		 *	@access public
		 *	@return NULL
		 */
		public function reconnect()
		{
			$this->disconnect();
			$this->connect();
		}

		/*
		 *	Conecta ao banco de dados
		 *	@name connect
		 *	@access public
		 *	@return NULL
		 */
		public function connect()
		{
			try {
				$this->ConnectionLink = new PDO("sqlite2:" . $this->DBname);
				if(!$this->ConnectionLink)
				{
					$this->ConnectionLink = new PDO("sqlite:" . $this->DBname);
				}
			} catch (PDOException $e) {
				$this->LastError = TRUE;
			}
		}
		
		/*
		 *	Método que grava uma mensagem de log
		 *	@name __savelog
		 *	@access private
		 *	@return NULL
		 */
		public function __savelog()
		{
			$file = fopen($this->LOGFile, 'a');
			$log  = "-- --------------------------------------\n";
			$log .= "#########################################\n";
			$log .= "-- --------------------------------------\n";
			$log .= " Date: " . date('H:i:s d/m/Y') . "\n";
			$log .= "Error: " . $this->LastError . "\n";
			$log .= "Query:\n";
			$log .= "\n";
			$log .= $this->SQL . "\n";
			$log .= "\n";
			
			fwrite($file, $log);
			fclose($file);
		} // __savelog
		
		/*
		 *	Método que retorna um só valor de um select
		 *	@name GetOne
		 *	@access public
		 *	@param	$sql - Query a ser executada
		 *	@return mixed
		 */
		public function GetOne($sql, $col=0)
		{
			$result = $this->Execute($sql);
			return $result->FetchOne($col);
		} // GetOne
		
		/*
		 *	Método que retorna o valor do ultimo campo auto-incremento inserido
		 *	@name InsertID
		 *	@access public
		 *	@return integer
		 */
		public function InsertID()
		{
			return $this->ConnectionLink->lastInsertId();
		} // InsertID
		
		/*
		 *	Método que retorna se existe um registro na tabela conforme o where
		 *	@name Exists
		 *	@access public
		 *	@param $tabel - Tabela onde sera executada a busca
		 *	@param $where - Clausula where
		 *	@return boolean
		 */
		public function Exists($table, $where='1=1')
		{
			$sql = '
				select 
					count(*)
				from
					' . $table . '
				where
					' . $where . '
			';
			
			// Registra a query
			$this->SQL = $sql;
			
			// Executa a query
			$res = $this->GetOne($sql);
			
			if($res == 0)
			{
				return FALSE;
			}
			else
			{
				return TRUE;
			}
		} // Exists
		
		/*
		 *	Método que executa uma query
		 *	@name Execute
		 *	@access public
		 *	@param	$sql - Query a ser executada
		 *	@return Objeto MYSQLresultSet
		 */
		public function Execute($sql)
		{
			$this->SQL = $sql;
			try
			{
				$result = $this->ConnectionLink->prepare($sql);
			}
			catch (PDOException $e)
			{
				$LastError = $e->getMessage();
				$this->__savelog();
				return FALSE;
			}
			$result->execute();
			return new SQLITEresultSet($result);
		} // Execute
		
		
		/*
		 *	Método que executa varias queries
		 *	@name MultipleExecute
		 *	@access public
		 *	@param	$sql - Queries a serem executadas
		 *	@return Objeto MYSQLresultSet
		 */
		public function MultipleExecute($sql)
		{
			$this->SQL = $sql;
			
			$content = explode("\n", $sql);
			$query = "";
			$iCounter = 0;
			
			foreach($content as $sql_line)
			{
			
				if(trim($sql_line) != "" && strpos($sql_line, "--") === false)
				{
					$query .= $sql_line;
					
					if(preg_match("/;\s*$/", $sql_line))
					{
						$res = $this->Execute($query);
						
						if($res === FALSE)
						{
							return FALSE;
						}
						
						$query = "";
						$iCounter++;
					}
				}
				if($iCounter > 100)
				{
					sleep(1);
					$iCounter = 0;
				}
			}
			
			return TRUE;
		} // MultipleExecute
		
		
		/*
		 *	Método que insere um registro a partir de vetores
		 *	@name AutoExecute
		 *	@access public
		 *	@param $table - Tabela a ser executado, $record - Vetor com os indexes e valores, $method - insert ou update, $where - Condição no update
		 *	@return boolean
		 */
		public function AutoExecute($table, $record, $method, $where=null)
		{
			
			// Monta a query de insert
			if($method == 'insert')
			{
				$sql 		= 'insert into ' . $table;
				$sqlFields	= '(';
				$sqlValues	= '(';
				foreach($record as $field => $value)
				{
					$sqlFields .= $field . ', ';
					$sqlValues .= '\'' . $value . '\', ';
				}
				$sqlFields = substr($sqlFields, 0, strlen($sqlFields) - 2) . ')';
				$sqlValues = substr($sqlValues, 0, strlen($sqlValues) - 2) . ')';
				$sql .= ' ' . $sqlFields . ' values ' . $sqlValues . ';';
				
			// Monta a query de update
			}
			elseif($method == 'update')
			{
				$sql 		= 'update ' . $table . ' set';
				foreach($record as $field => $value)
				{
					$sql .= ' ' . $field . ' = \'' . $value . '\',';
				}
				$sql = substr($sql, 0, strlen($sql) - 1);
				$sql .= ' where ' . $where;
			}

			// Registra o SQL
			$this->SQL = $sql;
			
			// Executa a query
			$res = $this->Execute($sql);
			if($res === FALSE)
			{
				return FALSE;
			}
			return TRUE;
		} // AutoExecute
		
	} // SQLITE
?>







